package com.sc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;
import com.mybatisflex.spring.service.impl.CacheableServiceImpl;
import com.sc.entity.Student;
import com.sc.exception.ServiceException;
import com.sc.mapper.StudentMapper;
import com.sc.service.DictionariesService;
import com.sc.service.StudentService;
import com.sc.vo.StudentVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

import static com.mybatisflex.core.query.QueryMethods.max;
import static com.sc.entity.table.StudentTableDef.STUDENT;

/**
 * 学生表 服务层实现。
 *
 * @author JoeZhou
 * @since 2024-09-14
 */
@Service
@CacheConfig(cacheNames = "student")
public class StudentServiceImpl extends CacheableServiceImpl<StudentMapper, Student> implements StudentService {
    @Autowired
    private DictionariesService dictionariesService;
    @Override
//    @Cacheable(key = "#id")
    public StudentVo getDetailById(Serializable id) {
        Student student = super.getById(id);
        StudentVo vo = BeanUtil.copyProperties(student, StudentVo.class);
        setDictionaryInfo(vo);
        return vo;
    }
    @Override
    @Cacheable(key = "#root.methodName")
    public Map<String, Object> totalStudent() {
        QueryWrapper queryWrapper = new QueryWrapper();
        long total = mapper.selectCountByQuery(queryWrapper);
        // 获得这一年年初的时间点 20xx-01-01T00:00
        LocalDateTime yearStartDateTime = LocalDateTime.now().toLocalDate().withMonth(1).withDayOfYear(1).atStartOfDay();
        queryWrapper.gt("created", yearStartDateTime);
        long increase = mapper.selectCountByQuery(queryWrapper);
        Map<String, Object> result = new HashMap<>();
        result.put("totalStudent", total);
        result.put("increase", increase);
        return result;
    }

    @Override
    @Cacheable(key = "#root.methodName")
    public Map<String, Object> livingStudent() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("status", 1);
        long total = mapper.selectCountByQuery(queryWrapper);
        // 获得这一年年初的时间点 20xx-01-01T00:00
        LocalDateTime yearStartDateTime = LocalDateTime.now().toLocalDate().withMonth(1).withDayOfYear(1).atStartOfDay();
        queryWrapper.gt("created", yearStartDateTime);
        long increase = mapper.selectCountByQuery(queryWrapper);
        Map<String, Object> result = new HashMap<>();
        result.put("livingStudent", total);
        result.put("increase", increase);
        return result;
    }

    private synchronized String nextSno() {
        QueryWrapper query = new QueryWrapper()
                .select(max(STUDENT.SNO)).from(STUDENT);
        String maxEno = mapper.selectOneByQueryAs(query, String.class);
        int thisYear = LocalDate.now().getYear();
        if (maxEno == null) {
            return "S" + thisYear + "0001";
        } else {
            int number = Integer.parseInt(maxEno.substring(1));
            if (number / 10000 == thisYear)
                return "S" + (number + 1);
            else
                return "S" + thisYear + "0001";
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean save(Student entity) {
        // 查询学生的手机号是否重复
        QueryWrapper query = QueryWrapper.create().eq("phone", entity.getPhone());
        Student tmp = mapper.selectOneByQuery(query);
        if (tmp != null) {
            throw new ServiceException(String.format("新录入学生手机号码和学生[%s]重复~", tmp.getName()));
        }
        // 生成学号
        entity.setSno(nextSno());
        // 手机号后6位做密码
        String passwd = entity.getPhone().substring(5);
        // 使用md5对密码加密
        entity.setPasswd(SecureUtil.md5(passwd));
        // 查询一下该员工的信息及其部门信息
        return super.save(entity);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean remove(QueryWrapper query) {
        return super.remove(query);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean removeByIds(Collection<? extends Serializable> ids) {
        return super.removeByIds(ids);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean update(Student entity, QueryWrapper query) {
        return super.update(entity, query);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean updateById(Student entity, boolean ignoreNulls) {
        return super.updateById(entity, ignoreNulls);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean updateBatch(Collection<Student> entities, int batchSize) {
        return super.updateBatch(entities, batchSize);
    }

    @Override
    @Cacheable(key = "#id")
    public Student getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public Student getOne(QueryWrapper query) {
        return super.getOne(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> R getOneAs(QueryWrapper query, Class<R> asType) {
        return super.getOneAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public Object getObj(QueryWrapper query) {
        return super.getObj(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> R getObjAs(QueryWrapper query, Class<R> asType) {
        return super.getObjAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public List<Object> objList(QueryWrapper query) {
        return super.objList(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> List<R> objListAs(QueryWrapper query, Class<R> asType) {
        return super.objListAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public List<Student> list(QueryWrapper query) {
        return super.list(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> List<R> listAs(QueryWrapper query, Class<R> asType) {
        return super.listAs(query, asType);
    }

    /**
     * @deprecated 无法通过注解进行缓存操作。
     */
    @Override
    @Deprecated
    public List<Student> listByIds(Collection<? extends Serializable> ids) {
        return super.listByIds(ids);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public long count(QueryWrapper query) {
        return super.count(query);
    }


    @Override
    @Cacheable(key = "#root.methodName + ':' + #page.getPageSize() + ':' + #page.getPageNumber() + ':' + #query.toSQL()")
    public <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) {
        Page<R> temp = super.pageAs(page, query, asType);
        List<R> records = temp.getRecords();
        for (R r : records) {
            StudentVo vo = (StudentVo) r;
            setDictionaryInfo(vo);
        }
        return temp;
    }

    private void setDictionaryInfo(StudentVo vo) {
        vo.setGrade(dictionariesService.getNameById(vo.getGradeId()));
        vo.setSchool(dictionariesService.getNameById(vo.getSchoolId()));
        vo.setCollage(dictionariesService.getNameById(vo.getCollageId()));
        vo.setMajor(dictionariesService.getNameById(vo.getMajorId()));
        vo.setScmIds(Arrays.asList(vo.getSchoolId(), vo.getCollageId(), vo.getMajorId()));
    }
}
